This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

This version of beta calculation is used for the theoretical method/results of the paper. For reference: the last update was Dec 2018 for an R notebook. This R notebook is an updated and more sophisticated version.

Constants used are listed at the start of this script.

setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
#values needed 
K= 1.38064852*(10)^-23 #m2 kg/ s2 K boltzmann constant
mu= 1.126*(10)^-3 #kg/m s dynamic viscosity in 18C
v= 1.099*(10)^-6 #m2/s kinematic viscosity in 18C
Reh_calc= 2.3E-6 #in m radius Ehux
Reh_naked= 1.8E-6 #in m radius Ehux
Reh_lith = 1.25E-6 #in m radius
Rehv= 90*(10)^-9 #in m radius virus
Temp = 18+273.15 #temp in kelvin, here assuming 18C
Den_OcM = 1.05 #g/cm3 density organic cell matter
Den_CH2O= 1.025 #g/cm3 density seawater at 18C
hostnum <- (10)^3
virnum <- hostnum*10
lithnum <- hostnum*50
require (ggplot2)
Loading required package: ggplot2
package 㤼㸱ggplot2㤼㸲 was built under R version 3.5.3
require(plotly)
Loading required package: plotly
package 㤼㸱plotly㤼㸲 was built under R version 3.5.3
Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
require(grid)
Loading required package: grid
require(ggthemes)
Loading required package: ggthemes
package 㤼㸱ggthemes㤼㸲 was built under R version 3.5.3
require (dplyr)
Loading required package: dplyr
package 㤼㸱dplyr㤼㸲 was built under R version 3.5.3
Attaching package: 㤼㸱dplyr㤼㸲

The following objects are masked from 㤼㸱package:stats㤼㸲:

    filter, lag

The following objects are masked from 㤼㸱package:base㤼㸲:

    intersect, setdiff, setequal, union
require(plyr)
Loading required package: plyr
----------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
----------------------------------------------------------------------------------------------------------------

Attaching package: 㤼㸱plyr㤼㸲

The following objects are masked from 㤼㸱package:dplyr㤼㸲:

    arrange, count, desc, failwith, id, mutate, rename, summarise, summarize

The following objects are masked from 㤼㸱package:plotly㤼㸲:

    arrange, mutate, rename, summarise
require(tidyverse)
Loading required package: tidyverse
package 㤼㸱tidyverse㤼㸲 was built under R version 3.5.3-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
v tibble  2.1.3     v purrr   0.3.2
v tidyr   0.8.3     v stringr 1.4.0
v readr   1.3.1     v forcats 0.4.0
package 㤼㸱tibble㤼㸲 was built under R version 3.5.3package 㤼㸱tidyr㤼㸲 was built under R version 3.5.3package 㤼㸱readr㤼㸲 was built under R version 3.5.3package 㤼㸱purrr㤼㸲 was built under R version 3.5.3package 㤼㸱stringr㤼㸲 was built under R version 3.5.3package 㤼㸱forcats㤼㸲 was built under R version 3.5.3-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x plyr::arrange()   masks dplyr::arrange(), plotly::arrange()
x purrr::compact()  masks plyr::compact()
x plyr::count()     masks dplyr::count()
x plyr::failwith()  masks dplyr::failwith()
x dplyr::filter()   masks plotly::filter(), stats::filter()
x plyr::id()        masks dplyr::id()
x dplyr::lag()      masks stats::lag()
x plyr::mutate()    masks dplyr::mutate(), plotly::mutate()
x plyr::rename()    masks dplyr::rename(), plotly::rename()
x plyr::summarise() masks dplyr::summarise(), plotly::summarise()
x plyr::summarize() masks dplyr::summarize()
source ("theme_Publication.R")
grid.newpage()

Calculating for Brownian motion

#Brownian motion (BM)
#1. make a data frame
BM <- data.frame (group=as.factor(c("Nc", "Cc", "Li")), rad= c(1.8E-6, 2.3E-6, 1.5E-6)) 
#2. calculate beta (beta)
BM$beta_BM <- ((2*(K*(10)^4)*Temp*(((BM$rad+Rehv)*100)^2))/((3*mu*10)*(BM$rad*Rehv*1e4)))*86400 #cm3/d
# go back to this later
#3. calculate encounters (E)
BM$E_BM <- BM$beta_BM*virnum
BM

Differential settling

#Differential settling (DS)
#1. read in PIC data
library(readr) #always use readr not baseR
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
PIC <- read_csv("Postdoc-R/CSV Files/PIC.csv")
Parsed with column specification:
cols(
  Strain = col_character(),
  Replicate = col_double(),
  TC = col_double(),
  AC = col_double(),
  Cellcount = col_double()
)
PIC$Strain <- as.factor(PIC$Strain)
PIC$Replicate <- as.factor(PIC$Replicate)
#2. calculate PIC for cell
PIC$PIC <- PIC$TC-PIC$AC
PIC$PICpercell <- (PIC$PIC/PIC$Cellcount)*(10)^-3#in g
PIC$PICpercellpg <- PIC$PICpercell*1e12
ggplotly(ggplot(data=PIC, aes(x=Strain, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2) +theme_Publication())

#3a. calculate density of cells (den_cell)
PIC <- mutate(PIC, group = ifelse(PICpercellpg < 4 , "naked", "calcified"))
ggplotly(ggplot(data=PIC, aes(x=group, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2, aes(color=Strain))+ theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

PIC <- mutate(PIC, rad = ifelse(group == "naked" , 1.8E-6,  2.3E-6)) #in m
PIC$volume <- (4/3)*pi*(PIC$rad*100)^3 #in cm3
PIC$Den_cell <- PIC$PICpercell/PIC$volume #g/cm3
PIC$Den_celltotal <- PIC$Den_cell+Den_OcM
ggplotly(ggplot(data=PIC, aes(x=Strain, y=Den_celltotal, color=group)) + geom_boxplot()+geom_point(size=2) 
         +theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

#some strains that are "naked" have PIC<2. I chose to ignore this since in the lm model I do not use
#strain as a factor, rather data is treated as a whole (e.g., no grouping)
#3b. calculate PIC and density for lith
lithvol <- 3*1e-12 #in cm3, from CJ's paper
PIC$perlith <- PIC$PICpercell/20 #in g, assuming 20 liths attached
PIC$perlithpg <- PIC$perlith*1e12 #in pg
PIC$Denlith <- (PIC$perlith/lithvol) + Den_OcM #in g/cm3, with organic matter attached
PIC$Denlith_noOCM <- (PIC$perlith/lithvol) #in g/cm3, without organic matter attached
#assume grouping
PIC$group2 <- case_when(
  PIC$PICpercellpg <2  ~ "naked",
  PIC$PICpercellpg >2 & PIC$PICpercellpg < 4 ~ "naked/calcified uncertain",
  PIC$PICpercellpg >4 & PIC$PICpercellpg < 10 ~ "moderately calcified",
  PIC$PICpercellpg >10 ~ "heavily calcified", 
  TRUE ~ as.character(PIC$PICpercellpg)
)
#4. calculate sinking velocity of cells,liths, and viruses
PIC$SinkVel <- ((2*((PIC$rad*100)^2)*(981)*(PIC$Den_celltotal-Den_CH2O))/(9*(mu*10)))*864 #meter per day
PIC$SinkVel_lith <- ((2*((Reh_lith*100)^2)*(981)*(PIC$Denlith-Den_CH2O))/(9*(mu*10)))*864 #meter per day
Ehv_SinkVel <- ((2*((Rehv*100)^2)*(981)*(Den_CH2O-Den_CH2O))/(9*(mu*10)))*864  #equals to 0
#g is converted to per day, 864 is the one that converts cm/s to m/day
#plot sinking velocity vs calcification
ggplot(data=PIC, aes(x=PICpercellpg, y=SinkVel, color=Strain, shape=str_wrap(group2, 20))) + geom_point(size=5)+theme_Publication()+
    labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~cell^-1)) +
    theme(legend.direction = "horizontal", legend.box = "vertical", legend.title = element_blank()) 

ggplot(data=PIC, aes(x=perlithpg, y=SinkVel_lith, color=Strain, shape=str_wrap(group2, 20))) + 
  geom_point(size=5)+theme_Publication()+
  labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~lith^-1)) +
    theme(legend.direction = "horizontal", legend.box = "vertical", legend.title = element_blank()) 

#6. calculate encounters
PIC$E_DS <- (PIC$beta_DS*virnum) #E calculated with Virus for cell
PIC$E_DS_lith <- (PIC$beta_DS_lith*virnum) #E calculated with Virus for lith
ggplotly(ggplot(data=PIC, aes(x=PICpercellpg, y=log10(E_DS))) +geom_point(size=5, aes(shape=group2, color=Strain)) +
    theme_Publication() + geom_smooth())
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

#remove strains 621, 623, 625
PIC <- PIC %>% filter (! Strain %in% c("621", "623", "655"))
ggplot(data=PIC, aes(x=PICpercellpg, y=E_DS, color=Strain, shape=str_wrap(group2, 20))) + geom_point(size=5)+theme_Publication()+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
      theme(legend.direction = "horizontal", legend.box = "vertical", legend.title = element_blank()) 

ggplot(data=PIC, aes(x=perlithpg, y=E_DS_lith, color=Strain, shape=str_wrap(group2, 20))) + geom_point(size=5)+theme_Publication()+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
      theme(legend.direction = "horizontal", legend.box = "vertical", legend.title = element_blank()) 

#7. summaries
summary_DS <- ddply(PIC, .(Strain), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                    Den_celltotal = mean (Den_celltotal),SinkVel=mean(SinkVel),beta_DS=mean(beta_DS), E_DS= mean(E_DS),
                    Denlith = mean (Denlith), SinkVel_lith=mean (SinkVel_lith), 
                    beta_DS_lith=mean (beta_DS_lith), E_DS_lith=mean (E_DS_lith))
summary_DS_bygroup <- ddply(PIC, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                    Den_celltotal = mean (Den_celltotal), SinkVel=mean(SinkVel),beta_DS=mean(beta_DS), E_DS= mean(E_DS),
                    Denlith = mean (Denlith), SinkVel_lith=mean (SinkVel_lith), 
                    beta_DS_lith=mean (beta_DS_lith), E_DS_lith=mean (E_DS_lith))
summary_DS
summary_DS_bygroup
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
require(openxlsx)
Loading required package: openxlsx
package 㤼㸱openxlsx㤼㸲 was built under R version 3.5.3
write.xlsx(summary_DS, file = "Postdoc-R/Exported Tables/summary_DS.xlsx")
Note: zip::zip() is deprecated, please use zip::zipr() instead
write.xlsx(summary_DS_bygroup, file = "Postdoc-R/Exported Tables/summary_DS_bygroup.xlsx")
#8. regressions
#8a. PIC and sinkvel of cells 
PIC_reg <- lm(SinkVel~PICpercellpg, data=PIC) 
summary(PIC_reg)

Call:
lm(formula = SinkVel ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0075101 -0.0021196  0.0001935  0.0015029  0.0106975 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.0191654  0.0008908   21.51   <2e-16 ***
PICpercellpg 0.0176146  0.0001047  168.20   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.004047 on 35 degrees of freedom
Multiple R-squared:  0.9988,    Adjusted R-squared:  0.9987 
F-statistic: 2.829e+04 on 1 and 35 DF,  p-value: < 2.2e-16
plot(residuals.lm(PIC_reg))

coef(PIC_reg)
 (Intercept) PICpercellpg 
  0.01916536   0.01761463 
cor(PIC$PICpercellpg, PIC$SinkVel)
[1] 0.999382
#8b. PIC and sinkvel of liths
PICSinkVel_lith_reg <- lm(SinkVel_lith~perlithpg, data = PIC)
summary(PICSinkVel_lith_reg)
essentially perfect fit: summary may be unreliable

Call:
lm(formula = SinkVel_lith ~ perlithpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-3.110e-17 -1.378e-17 -1.778e-18  1.222e-17  3.317e-17 

Coefficients:
             Estimate Std. Error   t value Pr(>|t|)    
(Intercept) 6.534e-03  3.662e-18 1.784e+15   <2e-16 ***
perlithpg   8.712e-02  8.611e-18 1.012e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.664e-17 on 35 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 1.024e+32 on 1 and 35 DF,  p-value: < 2.2e-16
plot(residuals.lm(PICSinkVel_lith_reg))

coef(PICSinkVel_lith_reg)
(Intercept)   perlithpg 
0.006534192 0.087122558 
cor(PIC$perlithpg, PIC$SinkVel_lith)
[1] 1
#8c. for PIC of liths depending on PICs of cells
PIC_lith_reg <- lm (perlithpg~PICpercellpg, data=PIC)
summary(PIC_lith_reg)
essentially perfect fit: summary may be unreliable

Call:
lm(formula = perlithpg ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-4.012e-16 -1.880e-17  9.870e-18  2.897e-17  1.908e-16 

Coefficients:
               Estimate Std. Error    t value Pr(>|t|)    
(Intercept)  -3.650e-17  1.902e-17 -1.919e+00   0.0632 .  
PICpercellpg  5.000e-02  2.236e-18  2.236e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.641e-17 on 35 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 4.999e+32 on 1 and 35 DF,  p-value: < 2.2e-16
plot(residuals.lm(PIC_lith_reg))

coef(PIC_lith_reg)
  (Intercept)  PICpercellpg 
-3.650391e-17  5.000000e-02 
cor(PIC$perlithpg, PIC$SinkVel_lith)
[1] 1
#8d. for sinking velocity of liths depending on PICs of cells
SinkVel_lith_reg <- lm (SinkVel_lith~PICpercellpg, data=PIC)
summary(SinkVel_lith_reg)
essentially perfect fit: summary may be unreliable

Call:
lm(formula = SinkVel_lith ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-5.558e-17 -1.279e-17  4.460e-19  1.647e-17  2.985e-17 

Coefficients:
              Estimate Std. Error   t value Pr(>|t|)    
(Intercept)  6.534e-03  4.341e-18 1.505e+15   <2e-16 ***
PICpercellpg 4.356e-03  5.103e-19 8.536e+15   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.972e-17 on 35 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 7.286e+31 on 1 and 35 DF,  p-value: < 2.2e-16
plot(residuals.lm(SinkVel_lith_reg))

coef(SinkVel_lith_reg)
 (Intercept) PICpercellpg 
 0.006534192  0.004356128 
cor(PIC$perlithpg, PIC$SinkVel_lith)
[1] 1
#
#10. calculate new beta and encounters based on newdata
PIC_newdata <- mutate(PIC_newdata, rad = ifelse(group == "naked" , 1.8E-6,  2.3E-6)) #in m
PIC_newdata$beta_DS <- (pi*(((PIC_newdata$rad+Rehv)*100)^2)*(abs((PIC_newdata$SinkVel.pred-Ehv_SinkVel)/864)))*86400 #in encounters cm3/day
PIC_newdata$beta_DS_lith <- (pi*(((Reh_lith+Rehv)*100)^2)*(abs((PIC_newdata$SinkVel.pred.lith-Ehv_SinkVel)/864)))*86400 #in encounters cm3/day
PIC_newdata$E_DS <- (PIC_newdata$beta_DS*virnum) #E calculated with Virus for cell
PIC_newdata$E_DS_lith <- (PIC_newdata$beta_DS_lith*virnum) #E calculated with Virus for cell
ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

summary_DS_bygroup_pred <- ddply(PIC_newdata, .(group2), summarize, PICpercellpg=mean(PICpercellpg),
                    perlithpg.pred = mean(perlithpg.pred), SinkVel.pred=mean(SinkVel.pred),beta_DS=mean(beta_DS), 
                    E_DS= mean(E_DS), SinkVel.pred.lith=mean (SinkVel.pred.lith), 
                    beta_DS_lith=mean (beta_DS_lith), E_DS_lith=mean (E_DS_lith))
summary_DS_bygroup_pred
#remove naked/calcified uncertain
PIC_newdata.trim <- PIC_newdata %>% filter (! group2 %in% c("naked/calcified uncertain"))
ggplot(data=PIC_newdata.trim, aes(x=PICpercellpg, y=E_DS)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
write.xlsx(summary_DS_bygroup_pred, file = "Postdoc-R/Exported Tables/summary_DS_bygroup_pred.xlsx")
cannot create file 'Postdoc-R/Exported Tables/summary_DS_bygroup_pred.xlsx', reason 'Permission denied'

Turbulence

#Turbulence
#1. make new dataframe
LS0tDQp0aXRsZTogImJldGEga2VybmVsIGZvciBwYXBlciINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIA0KDQpUaGlzIHZlcnNpb24gb2YgYmV0YSBjYWxjdWxhdGlvbiBpcyB1c2VkIGZvciB0aGUgdGhlb3JldGljYWwgbWV0aG9kL3Jlc3VsdHMgb2YgdGhlIHBhcGVyLiBGb3IgcmVmZXJlbmNlOiB0aGUgbGFzdCB1cGRhdGUgd2FzIERlYyAyMDE4IGZvciBhbiBSIG5vdGVib29rLiBUaGlzIFIgbm90ZWJvb2sgaXMgYW4gdXBkYXRlZCBhbmQgbW9yZSBzb3BoaXN0aWNhdGVkIHZlcnNpb24uIA0KDQpDb25zdGFudHMgdXNlZCBhcmUgbGlzdGVkIGF0IHRoZSBzdGFydCBvZiB0aGlzIHNjcmlwdC4NCg0KYGBge3J9DQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNCiN2YWx1ZXMgbmVlZGVkIA0KDQpLPSAxLjM4MDY0ODUyKigxMCleLTIzICNtMiBrZy8gczIgSyBib2x0em1hbm4gY29uc3RhbnQNCm11PSAxLjEyNiooMTApXi0zICNrZy9tIHMgZHluYW1pYyB2aXNjb3NpdHkgaW4gMThDDQp2PSAxLjA5OSooMTApXi02ICNtMi9zIGtpbmVtYXRpYyB2aXNjb3NpdHkgaW4gMThDDQpSZWhfY2FsYz0gMi4zRS02ICNpbiBtIHJhZGl1cyBFaHV4DQpSZWhfbmFrZWQ9IDEuOEUtNiAjaW4gbSByYWRpdXMgRWh1eA0KUmVoX2xpdGggPSAxLjI1RS02ICNpbiBtIHJhZGl1cw0KUmVodj0gOTAqKDEwKV4tOSAjaW4gbSByYWRpdXMgdmlydXMNClRlbXAgPSAxOCsyNzMuMTUgI3RlbXAgaW4ga2VsdmluLCBoZXJlIGFzc3VtaW5nIDE4Qw0KRGVuX09jTSA9IDEuMDUgI2cvY20zIGRlbnNpdHkgb3JnYW5pYyBjZWxsIG1hdHRlcg0KRGVuX0NIMk89IDEuMDI1ICNnL2NtMyBkZW5zaXR5IHNlYXdhdGVyIGF0IDE4Qw0KaG9zdG51bSA8LSAoMTApXjMNCnZpcm51bSA8LSBob3N0bnVtKjEwDQpsaXRobnVtIDwtIGhvc3RudW0qNTANCg0KcmVxdWlyZSAoZ2dwbG90MikNCnJlcXVpcmUocGxvdGx5KQ0KcmVxdWlyZShncmlkKQ0KcmVxdWlyZShnZ3RoZW1lcykNCnJlcXVpcmUgKGRwbHlyKQ0KcmVxdWlyZShwbHlyKQ0KcmVxdWlyZSh0aWR5dmVyc2UpDQpzb3VyY2UgKCJ0aGVtZV9QdWJsaWNhdGlvbi5SIikNCmdyaWQubmV3cGFnZSgpDQpgYGANCg0KQ2FsY3VsYXRpbmcgZm9yIEJyb3duaWFuIG1vdGlvbg0KDQpgYGB7cn0NCiNCcm93bmlhbiBtb3Rpb24gKEJNKQ0KIzEuIG1ha2UgYSBkYXRhIGZyYW1lDQpCTSA8LSBkYXRhLmZyYW1lIChncm91cD1hcy5mYWN0b3IoYygiTmMiLCAiQ2MiLCAiTGkiKSksIHJhZD0gYygxLjhFLTYsIDIuM0UtNiwgMS41RS02KSkgDQoNCiMyLiBjYWxjdWxhdGUgYmV0YSAoYmV0YSkNCkJNJGJldGFfQk0gPC0gKCgyKihLKigxMCleNCkqVGVtcCooKChCTSRyYWQrUmVodikqMTAwKV4yKSkvKCgzKm11KjEwKSooQk0kcmFkKlJlaHYqMWU0KSkpKjg2NDAwICNjbTMvZA0KDQojIGdvIGJhY2sgdG8gdGhpcyBsYXRlcg0KIzMuIGNhbGN1bGF0ZSBlbmNvdW50ZXJzIChFKQ0KQk0kRV9CTSA8LSBCTSRiZXRhX0JNKnZpcm51bQ0KDQpCTQ0KYGBgDQoNCkRpZmZlcmVudGlhbCBzZXR0bGluZw0KYGBge3J9DQojRGlmZmVyZW50aWFsIHNldHRsaW5nIChEUykNCiMxLiByZWFkIGluIFBJQyBkYXRhDQpsaWJyYXJ5KHJlYWRyKSAjYWx3YXlzIHVzZSByZWFkciBub3QgYmFzZVINCg0Kc2V0d2QoIkQ6L1IgcHJvZ3JhbSIpDQpQSUMgPC0gcmVhZF9jc3YoIlBvc3Rkb2MtUi9DU1YgRmlsZXMvUElDLmNzdiIpDQoNClBJQyRTdHJhaW4gPC0gYXMuZmFjdG9yKFBJQyRTdHJhaW4pDQpQSUMkUmVwbGljYXRlIDwtIGFzLmZhY3RvcihQSUMkUmVwbGljYXRlKQ0KDQojMi4gY2FsY3VsYXRlIFBJQyBmb3IgY2VsbA0KUElDJFBJQyA8LSBQSUMkVEMtUElDJEFDDQpQSUMkUElDcGVyY2VsbCA8LSAoUElDJFBJQy9QSUMkQ2VsbGNvdW50KSooMTApXi0zI2luIGcNClBJQyRQSUNwZXJjZWxscGcgPC0gUElDJFBJQ3BlcmNlbGwqMWUxMg0KDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVN0cmFpbiwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKSArdGhlbWVfUHVibGljYXRpb24oKSkNCg0KIzNhLiBjYWxjdWxhdGUgZGVuc2l0eSBvZiBjZWxscyAoZGVuX2NlbGwpDQpQSUMgPC0gbXV0YXRlKFBJQywgZ3JvdXAgPSBpZmVsc2UoUElDcGVyY2VsbHBnIDwgNCAsICJuYWtlZCIsICJjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1ncm91cCwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yLCBhZXMoY29sb3I9U3RyYWluKSkrIHRoZW1lX1B1YmxpY2F0aW9uKCkpDQoNClBJQyA8LSBtdXRhdGUoUElDLCByYWQgPSBpZmVsc2UoZ3JvdXAgPT0gIm5ha2VkIiAsIDEuOEUtNiwgIDIuM0UtNikpICNpbiBtDQoNClBJQyR2b2x1bWUgPC0gKDQvMykqcGkqKFBJQyRyYWQqMTAwKV4zICNpbiBjbTMNClBJQyREZW5fY2VsbCA8LSBQSUMkUElDcGVyY2VsbC9QSUMkdm9sdW1lICNnL2NtMw0KUElDJERlbl9jZWxsdG90YWwgPC0gUElDJERlbl9jZWxsK0Rlbl9PY00NCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9RGVuX2NlbGx0b3RhbCwgY29sb3I9Z3JvdXApKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKSANCiAgICAgICAgICt0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQojc29tZSBzdHJhaW5zIHRoYXQgYXJlICJuYWtlZCIgaGF2ZSBQSUM8Mi4gSSBjaG9zZSB0byBpZ25vcmUgdGhpcyBzaW5jZSBpbiB0aGUgbG0gbW9kZWwgSSBkbyBub3QgdXNlDQojc3RyYWluIGFzIGEgZmFjdG9yLCByYXRoZXIgZGF0YSBpcyB0cmVhdGVkIGFzIGEgd2hvbGUgKGUuZy4sIG5vIGdyb3VwaW5nKQ0KDQojM2IuIGNhbGN1bGF0ZSBQSUMgYW5kIGRlbnNpdHkgZm9yIGxpdGgNCmxpdGh2b2wgPC0gMyoxZS0xMiAjaW4gY20zLCBmcm9tIENKJ3MgcGFwZXINClBJQyRwZXJsaXRoIDwtIFBJQyRQSUNwZXJjZWxsLzIwICNpbiBnLCBhc3N1bWluZyAyMCBsaXRocyBhdHRhY2hlZA0KUElDJHBlcmxpdGhwZyA8LSBQSUMkcGVybGl0aCoxZTEyICNpbiBwZw0KUElDJERlbmxpdGggPC0gKFBJQyRwZXJsaXRoL2xpdGh2b2wpICsgRGVuX09jTSAjaW4gZy9jbTMsIHdpdGggb3JnYW5pYyBtYXR0ZXIgYXR0YWNoZWQNClBJQyREZW5saXRoX25vT0NNIDwtIChQSUMkcGVybGl0aC9saXRodm9sKSAjaW4gZy9jbTMsIHdpdGhvdXQgb3JnYW5pYyBtYXR0ZXIgYXR0YWNoZWQNCmBgYA0KYGBge3J9DQojYXNzdW1lIGdyb3VwaW5nDQpQSUMkZ3JvdXAyIDwtIGNhc2Vfd2hlbigNCiAgUElDJFBJQ3BlcmNlbGxwZyA8MiAgfiAibmFrZWQiLA0KICBQSUMkUElDcGVyY2VsbHBnID4yICYgUElDJFBJQ3BlcmNlbGxwZyA8IDQgfiAibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsDQogIFBJQyRQSUNwZXJjZWxscGcgPjQgJiBQSUMkUElDcGVyY2VsbHBnIDwgMTAgfiAibW9kZXJhdGVseSBjYWxjaWZpZWQiLA0KICBQSUMkUElDcGVyY2VsbHBnID4xMCB+ICJoZWF2aWx5IGNhbGNpZmllZCIsIA0KICBUUlVFIH4gYXMuY2hhcmFjdGVyKFBJQyRQSUNwZXJjZWxscGcpDQopDQoNCmBgYA0KDQpgYGB7cn0NCiM0LiBjYWxjdWxhdGUgc2lua2luZyB2ZWxvY2l0eSBvZiBjZWxscyxsaXRocywgYW5kIHZpcnVzZXMNClBJQyRTaW5rVmVsIDwtICgoMiooKFBJQyRyYWQqMTAwKV4yKSooOTgxKSooUElDJERlbl9jZWxsdG90YWwtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICNtZXRlciBwZXIgZGF5DQpQSUMkU2lua1ZlbF9saXRoIDwtICgoMiooKFJlaF9saXRoKjEwMCleMikqKDk4MSkqKFBJQyREZW5saXRoLURlbl9DSDJPKSkvKDkqKG11KjEwKSkpKjg2NCAjbWV0ZXIgcGVyIGRheQ0KRWh2X1NpbmtWZWwgPC0gKCgyKigoUmVodioxMDApXjIpKig5ODEpKihEZW5fQ0gyTy1EZW5fQ0gyTykpLyg5KihtdSoxMCkpKSo4NjQgICNlcXVhbHMgdG8gMA0KI2cgaXMgY29udmVydGVkIHRvIHBlciBkYXksIDg2NCBpcyB0aGUgb25lIHRoYXQgY29udmVydHMgY20vcyB0byBtL2RheQ0KI3Bsb3Qgc2lua2luZyB2ZWxvY2l0eSB2cyBjYWxjaWZpY2F0aW9uDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9UElDcGVyY2VsbHBnLCB5PVNpbmtWZWwsIGNvbG9yPVN0cmFpbiwgc2hhcGU9c3RyX3dyYXAoZ3JvdXAyLCAyMCkpKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oIlNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmNlbGxeLTEpKSArDQogICAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9cGVybGl0aHBnLCB5PVNpbmtWZWxfbGl0aCwgY29sb3I9U3RyYWluLCBzaGFwZT1zdHJfd3JhcChncm91cDIsIDIwKSkpICsgDQogIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJTaW5raW5nIHZlbG9jaXR5In4oIm0ifmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5saXRoXi0xKSkgKw0KICAgIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsIGxlZ2VuZC5ib3ggPSAidmVydGljYWwiLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpIA0KDQoNCmBgYA0KYGBge3J9DQojNS4gY2FsY3VsYXRlIGJldGFzIGZvciBEUw0KUElDJGJldGFfRFMgPC0ocGkqKCgoUElDJHJhZCtSZWh2KSoxMDApXjIpKihhYnMoKFBJQyRTaW5rVmVsLUVodl9TaW5rVmVsKS84NjQpKSkqODY0MDAgI2luIGVuY291bnRlcnMgY20zL2RheQ0KUElDJGJldGFfRFNfbGl0aCA8LSAocGkqKCgoUmVoX2xpdGgrUmVodikqMTAwKV4yKSooYWJzKChQSUMkU2lua1ZlbF9saXRoLUVodl9TaW5rVmVsKS84NjQpKSkqODY0MDAgI2luIGVuY291bnRlcnMgY20zL2RheQ0KDQpnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVBJQ3BlcmNlbGxwZywgeT1iZXRhX0RTLCBjb2xvcj1TdHJhaW4sIHNoYXBlPXN0cl93cmFwKGdyb3VwMiwgMjApKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbihiZXRhfigiRW5jb3VudGVycyJ+Y21eM35kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+Y2VsbF4tMSkpICArDQpzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpKw0KICAgICAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgDQoNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1wZXJsaXRocGcsIHk9YmV0YV9EU19saXRoLCBjb2xvcj1TdHJhaW4sIHNoYXBlPXN0cl93cmFwKGdyb3VwMiwgMjApKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbihiZXRhfigiRW5jb3VudGVycyJ+Y21eM35kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+bGl0aF4tMSkpICArDQpzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpKw0KICAgICAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIzYuIGNhbGN1bGF0ZSBlbmNvdW50ZXJzDQpQSUMkRV9EUyA8LSAoUElDJGJldGFfRFMqdmlybnVtKSAjRSBjYWxjdWxhdGVkIHdpdGggVmlydXMgZm9yIGNlbGwNClBJQyRFX0RTX2xpdGggPC0gKFBJQyRiZXRhX0RTX2xpdGgqdmlybnVtKSAjRSBjYWxjdWxhdGVkIHdpdGggVmlydXMgZm9yIGxpdGgNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9bG9nMTAoRV9EUykpKSArZ2VvbV9wb2ludChzaXplPTUsIGFlcyhzaGFwZT1ncm91cDIsIGNvbG9yPVN0cmFpbikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSkNCiNyZW1vdmUgc3RyYWlucyA2MjEsIDYyMywgNjI1DQpQSUMgPC0gUElDICU+JSBmaWx0ZXIgKCEgU3RyYWluICVpbiUgYygiNjIxIiwgIjYyMyIsICI2NTUiKSkNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EUywgY29sb3I9U3RyYWluLCBzaGFwZT1zdHJfd3JhcChncm91cDIsIDIwKSkpICsgZ2VvbV9wb2ludChzaXplPTUpK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICAgICAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9cGVybGl0aHBnLCB5PUVfRFNfbGl0aCwgY29sb3I9U3RyYWluLCBzaGFwZT1zdHJfd3JhcChncm91cDIsIDIwKSkpICsgZ2VvbV9wb2ludChzaXplPTUpK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICAgICAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgDQpgYGANCg0KYGBge3J9DQojNy4gc3VtbWFyaWVzDQpzdW1tYXJ5X0RTIDwtIGRkcGx5KFBJQywgLihTdHJhaW4pLCBzdW1tYXJpemUsICBQSUNwZXJjZWxscGc9bWVhbihQSUNwZXJjZWxscGcpLCBwZXJsaXRocGcgPSBtZWFuKHBlcmxpdGhwZyksIA0KICAgICAgICAgICAgICAgICAgICBEZW5fY2VsbHRvdGFsID0gbWVhbiAoRGVuX2NlbGx0b3RhbCksU2lua1ZlbD1tZWFuKFNpbmtWZWwpLGJldGFfRFM9bWVhbihiZXRhX0RTKSwgRV9EUz0gbWVhbihFX0RTKSwNCiAgICAgICAgICAgICAgICAgICAgRGVubGl0aCA9IG1lYW4gKERlbmxpdGgpLCBTaW5rVmVsX2xpdGg9bWVhbiAoU2lua1ZlbF9saXRoKSwgDQogICAgICAgICAgICAgICAgICAgIGJldGFfRFNfbGl0aD1tZWFuIChiZXRhX0RTX2xpdGgpLCBFX0RTX2xpdGg9bWVhbiAoRV9EU19saXRoKSkNCnN1bW1hcnlfRFNfYnlncm91cCA8LSBkZHBseShQSUMsIC4oZ3JvdXAyKSwgc3VtbWFyaXplLCAgUElDcGVyY2VsbHBnPW1lYW4oUElDcGVyY2VsbHBnKSwgcGVybGl0aHBnID0gbWVhbihwZXJsaXRocGcpLCANCiAgICAgICAgICAgICAgICAgICAgRGVuX2NlbGx0b3RhbCA9IG1lYW4gKERlbl9jZWxsdG90YWwpLCBTaW5rVmVsPW1lYW4oU2lua1ZlbCksYmV0YV9EUz1tZWFuKGJldGFfRFMpLCBFX0RTPSBtZWFuKEVfRFMpLA0KICAgICAgICAgICAgICAgICAgICBEZW5saXRoID0gbWVhbiAoRGVubGl0aCksIFNpbmtWZWxfbGl0aD1tZWFuIChTaW5rVmVsX2xpdGgpLCANCiAgICAgICAgICAgICAgICAgICAgYmV0YV9EU19saXRoPW1lYW4gKGJldGFfRFNfbGl0aCksIEVfRFNfbGl0aD1tZWFuIChFX0RTX2xpdGgpKQ0Kc3VtbWFyeV9EUw0Kc3VtbWFyeV9EU19ieWdyb3VwDQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNCnJlcXVpcmUob3Blbnhsc3gpDQp3cml0ZS54bHN4KHN1bW1hcnlfRFMsIGZpbGUgPSAiUG9zdGRvYy1SL0V4cG9ydGVkIFRhYmxlcy9zdW1tYXJ5X0RTLnhsc3giKQ0Kd3JpdGUueGxzeChzdW1tYXJ5X0RTX2J5Z3JvdXAsIGZpbGUgPSAiUG9zdGRvYy1SL0V4cG9ydGVkIFRhYmxlcy9zdW1tYXJ5X0RTX2J5Z3JvdXAueGxzeCIpDQpgYGANCg0KYGBge3J9DQojOC4gcmVncmVzc2lvbnMNCiM4YS4gUElDIGFuZCBzaW5rdmVsIG9mIGNlbGxzIA0KUElDX3JlZyA8LSBsbShTaW5rVmVsflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpIA0Kc3VtbWFyeShQSUNfcmVnKQ0KcGxvdChyZXNpZHVhbHMubG0oUElDX3JlZykpDQpjb2VmKFBJQ19yZWcpDQpjb3IoUElDJFBJQ3BlcmNlbGxwZywgUElDJFNpbmtWZWwpDQoNCiM4Yi4gUElDIGFuZCBzaW5rdmVsIG9mIGxpdGhzDQpQSUNTaW5rVmVsX2xpdGhfcmVnIDwtIGxtKFNpbmtWZWxfbGl0aH5wZXJsaXRocGcsIGRhdGEgPSBQSUMpDQpzdW1tYXJ5KFBJQ1NpbmtWZWxfbGl0aF9yZWcpDQpwbG90KHJlc2lkdWFscy5sbShQSUNTaW5rVmVsX2xpdGhfcmVnKSkNCmNvZWYoUElDU2lua1ZlbF9saXRoX3JlZykNCmNvcihQSUMkcGVybGl0aHBnLCBQSUMkU2lua1ZlbF9saXRoKQ0KDQojOGMuIGZvciBQSUMgb2YgbGl0aHMgZGVwZW5kaW5nIG9uIFBJQ3Mgb2YgY2VsbHMNClBJQ19saXRoX3JlZyA8LSBsbSAocGVybGl0aHBnflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpzdW1tYXJ5KFBJQ19saXRoX3JlZykNCnBsb3QocmVzaWR1YWxzLmxtKFBJQ19saXRoX3JlZykpDQpjb2VmKFBJQ19saXRoX3JlZykNCmNvcihQSUMkcGVybGl0aHBnLCBQSUMkU2lua1ZlbF9saXRoKQ0KDQojOGQuIGZvciBzaW5raW5nIHZlbG9jaXR5IG9mIGxpdGhzIGRlcGVuZGluZyBvbiBQSUNzIG9mIGNlbGxzDQpTaW5rVmVsX2xpdGhfcmVnIDwtIGxtIChTaW5rVmVsX2xpdGh+UElDcGVyY2VsbHBnLCBkYXRhPVBJQykNCnN1bW1hcnkoU2lua1ZlbF9saXRoX3JlZykNCnBsb3QocmVzaWR1YWxzLmxtKFNpbmtWZWxfbGl0aF9yZWcpKQ0KY29lZihTaW5rVmVsX2xpdGhfcmVnKQ0KY29yKFBJQyRwZXJsaXRocGcsIFBJQyRTaW5rVmVsX2xpdGgpDQoNCiMNCmBgYA0KDQpgYGB7cn0NCiM5LiBtYWtlIGEgcHJlZGljdGlvbiBiYXNlZCBvbiBQSUMgdmFsdWVzDQojOWEuIGZvciBjZWxscw0KcmVxdWlyZSh0cnVuY25vcm0pDQpyZXF1aXJlKFJtaXNjKQ0Kc3VtbWFyeShQSUMkUElDcGVyY2VsbHBnKQ0Kc3VtbWFyeVNFKGRhdGE9UElDLCBtZWFzdXJldmFyPSJQSUNwZXJjZWxscGciKQ0KDQojbWFrZSBuZXcgZGF0YWZyYW1lDQpQSUNfbmV3ZGF0YSA8LSBhcy5kYXRhLmZyYW1lKHJ0cnVuY25vcm0obj0xMDAwMCwgYT0tMC40LCBiPTIwLjIsIG1lYW49NS43LCBzZD02LjUpKQ0KI3JlbmFtZSBjb2x1bW4uIHJlbmFtZSBmdW5jdGlvbiBpbiBwbHlyIA0KbGlicmFyeShwbHlyKQ0KUElDX25ld2RhdGEgPC0gcmVuYW1lIChQSUNfbmV3ZGF0YSwgYyAoInJ0cnVuY25vcm0obiA9IDEwMDAwLCBhID0gLTAuNCwgYiA9IDIwLjIsIG1lYW4gPSA1LjcsIHNkID0gNi41KSIgPSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBJQ3BlcmNlbGxwZyIpKQ0KUElDX25ld2RhdGEgPC0gbXV0YXRlKFBJQ19uZXdkYXRhLCBncm91cCA9IGlmZWxzZShQSUNwZXJjZWxscGcgPCA0ICwgIm5ha2VkIiwgImNhbGNpZmllZCIpKQ0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PWdyb3VwLCB5PVBJQ3BlcmNlbGxwZykpICsgZ2VvbV9ib3hwbG90KCkrZ2VvbV9wb2ludChzaXplPTIpICsNCiAgICAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSkNCg0KUElDX25ld2RhdGEkZ3JvdXAyIDwtIGNhc2Vfd2hlbigNCiAgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnIDwyICB+ICJuYWtlZCIsDQogIFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZyA+MiAmIFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZyA8IDQgfiAibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsDQogIFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZyA+NCAmIFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZyA8IDEwIH4gIm1vZGVyYXRlbHkgY2FsY2lmaWVkIiwNCiAgUElDX25ld2RhdGEkUElDcGVyY2VsbHBnID4xMCB+ICJoZWF2aWx5IGNhbGNpZmllZCIsIA0KICBUUlVFIH4gYXMuY2hhcmFjdGVyKFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZykNCikNCg0KUElDX25ld2RhdGEkZ3JvdXAyIDwtIGZhY3RvciAoUElDX25ld2RhdGEkZ3JvdXAyLGxldmVscz0gYygibmFrZWQiLCAibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1vZGVyYXRlbHkgY2FsY2lmaWVkIiwgImhlYXZpbHkgY2FsY2lmaWVkIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygibmFrZWQiLCAibmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibW9kZXJhdGVseSBjYWxjaWZpZWQiLCAiaGVhdmlseSBjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PWdyb3VwMiwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKQ0KICAgICAgICAgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQoNCg0KDQojbWFrZSBuZXcgcHJlZGljdGlvbnMNClBJQ19uZXdkYXRhJFNpbmtWZWwucHJlZCA8LSBwcmVkaWN0KFBJQ19yZWcsIGRhdGEuZnJhbWUoUElDX25ld2RhdGEpKQ0KUElDX25ld2RhdGFfcmVnIDwtIGxtKFNpbmtWZWwucHJlZH5QSUNwZXJjZWxscGcsIGRhdGE9UElDX25ld2RhdGEpIA0KY29lZihQSUNfbmV3ZGF0YV9yZWcpDQpwbG90KHJlc2lkKFBJQ19uZXdkYXRhX3JlZykpDQpnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9UElDcGVyY2VsbHBnLCB5PVNpbmtWZWwucHJlZCkpICtnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oIlByZWRpY3RlZCBTaW5raW5nIHZlbG9jaXR5In4oIm0ifmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgDQojc2FtZSBjb2VmIGFzIFBJQ19yZWcNCg0KI2IuIGZvciBsaXRocw0KUElDX25ld2RhdGEkU2lua1ZlbC5wcmVkLmxpdGggPC0gcHJlZGljdChTaW5rVmVsX2xpdGhfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClBJQ19uZXdkYXRhJHBlcmxpdGhwZy5wcmVkIDwtIHByZWRpY3QoUElDX2xpdGhfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClNpbmtWZWxfbGl0aF9yZWcucHJlZCA8LSBsbShTaW5rVmVsLnByZWQubGl0aH5QSUNwZXJjZWxscGcsIGRhdGE9UElDX25ld2RhdGEpIA0KY29lZihTaW5rVmVsX2xpdGhfcmVnLnByZWQpDQpwbG90KHJlc2lkKFNpbmtWZWxfbGl0aF9yZWcucHJlZCkpDQpnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9cGVybGl0aHBnLnByZWQsIHk9U2lua1ZlbC5wcmVkLmxpdGgpKSArZ2VvbV9wb2ludChzaXplPTIpICt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJQcmVkaWN0ZWQgU2lua2luZyB2ZWxvY2l0eSBvZiBMaXRocyJ+KCJtIn5kYXleLTEpKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+bGl0aF4tMSkpIA0KDQpgYGANCg0KYGBge3J9DQojMTAuIGNhbGN1bGF0ZSBuZXcgYmV0YSBhbmQgZW5jb3VudGVycyBiYXNlZCBvbiBuZXdkYXRhDQpQSUNfbmV3ZGF0YSA8LSBtdXRhdGUoUElDX25ld2RhdGEsIHJhZCA9IGlmZWxzZShncm91cCA9PSAibmFrZWQiICwgMS44RS02LCAgMi4zRS02KSkgI2luIG0NClBJQ19uZXdkYXRhJGJldGFfRFMgPC0gKHBpKigoKFBJQ19uZXdkYXRhJHJhZCtSZWh2KSoxMDApXjIpKihhYnMoKFBJQ19uZXdkYXRhJFNpbmtWZWwucHJlZC1FaHZfU2lua1ZlbCkvODY0KSkpKjg2NDAwICNpbiBlbmNvdW50ZXJzIGNtMy9kYXkNClBJQ19uZXdkYXRhJGJldGFfRFNfbGl0aCA8LSAocGkqKCgoUmVoX2xpdGgrUmVodikqMTAwKV4yKSooYWJzKChQSUNfbmV3ZGF0YSRTaW5rVmVsLnByZWQubGl0aC1FaHZfU2lua1ZlbCkvODY0KSkpKjg2NDAwICNpbiBlbmNvdW50ZXJzIGNtMy9kYXkNClBJQ19uZXdkYXRhJEVfRFMgPC0gKFBJQ19uZXdkYXRhJGJldGFfRFMqdmlybnVtKSAjRSBjYWxjdWxhdGVkIHdpdGggVmlydXMgZm9yIGNlbGwNClBJQ19uZXdkYXRhJEVfRFNfbGl0aCA8LSAoUElDX25ld2RhdGEkYmV0YV9EU19saXRoKnZpcm51bSkgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzIGZvciBjZWxsDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EUykpICtnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPWdyb3VwMikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogICAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCnN1bW1hcnlfRFNfYnlncm91cF9wcmVkIDwtIGRkcGx5KFBJQ19uZXdkYXRhLCAuKGdyb3VwMiksIHN1bW1hcml6ZSwgUElDcGVyY2VsbHBnPW1lYW4oUElDcGVyY2VsbHBnKSwNCiAgICAgICAgICAgICAgICAgICAgcGVybGl0aHBnLnByZWQgPSBtZWFuKHBlcmxpdGhwZy5wcmVkKSwgU2lua1ZlbC5wcmVkPW1lYW4oU2lua1ZlbC5wcmVkKSxiZXRhX0RTPW1lYW4oYmV0YV9EUyksIA0KICAgICAgICAgICAgICAgICAgICBFX0RTPSBtZWFuKEVfRFMpLCBTaW5rVmVsLnByZWQubGl0aD1tZWFuIChTaW5rVmVsLnByZWQubGl0aCksIA0KICAgICAgICAgICAgICAgICAgICBiZXRhX0RTX2xpdGg9bWVhbiAoYmV0YV9EU19saXRoKSwgRV9EU19saXRoPW1lYW4gKEVfRFNfbGl0aCkpDQoNCnN1bW1hcnlfRFNfYnlncm91cF9wcmVkDQoNCiNyZW1vdmUgbmFrZWQvY2FsY2lmaWVkIHVuY2VydGFpbg0KUElDX25ld2RhdGEudHJpbSA8LSBQSUNfbmV3ZGF0YSAlPiUgZmlsdGVyICghIGdyb3VwMiAlaW4lIGMoIm5ha2VkL2NhbGNpZmllZCB1bmNlcnRhaW4iKSkNCg0KZ2dwbG90KGRhdGE9UElDX25ld2RhdGEudHJpbSwgYWVzKHg9UElDcGVyY2VsbHBnLCB5PUVfRFMpKSArZ2VvbV9wb2ludChzaXplPTUsIGFlcyhjb2xvcj1ncm91cDIpKSArDQogICAgdGhlbWVfUHVibGljYXRpb24oKSArIGdlb21fc21vb3RoKCkgKw0KICAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGRheV4tMX5jZWxsXi0xKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+Y2VsbF4tMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNCndyaXRlLnhsc3goc3VtbWFyeV9EU19ieWdyb3VwX3ByZWQsIGZpbGUgPSAiUG9zdGRvYy1SL0V4cG9ydGVkIFRhYmxlcy9zdW1tYXJ5X0RTX2J5Z3JvdXBfcHJlZC54bHN4IikNCmBgYA0KDQpUdXJidWxlbmNlDQpgYGB7cn0NCiNUdXJidWxlbmNlDQojMS4gbWFrZSBuZXcgZGF0YWZyYW1lDQoNCmBgYA0KDQo=